package com.gzhryc.shared_device.oem.code.place.services;

import com.gzhryc.common.StringTools;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.kafka.JFKafkaProducer;
import com.gzhryc.common.kafka.KafkaProducerFactory;
import com.gzhryc.common.kafka.models.KafkaMessage;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.jdbc.Conditions;
import com.gzhryc.jdbc.JdbcSession;
import com.gzhryc.jdbc.MultiDBTools;
import com.gzhryc.shared_device.base.IPlaceService;
import com.gzhryc.shared_device.base.models.OperateInfo;
import com.gzhryc.shared_device.common.device.dao.db.DeviceTypeFunc;
import com.gzhryc.shared_device.common.device.services.DeviceService;
import com.gzhryc.shared_device.common.device.services.DeviceTypeFuncService;
import com.gzhryc.shared_device.oem.code.KafkaEventConstants;
import com.gzhryc.shared_device.oem.code.agent.dao.db.Agent;
import com.gzhryc.shared_device.oem.code.agent.dao.db.AgentRelation;
import com.gzhryc.shared_device.oem.code.agent.services.AgentService;
import com.gzhryc.shared_device.oem.code.member.dao.enums.MemberBusinessOrderEnum;
import com.gzhryc.shared_device.oem.code.member.services.MemberBusinessOrderService;
import com.gzhryc.shared_device.oem.code.member.services.dto.MemberBusinessOrderSearch;
import com.gzhryc.shared_device.oem.code.place.dao.db.PlaceBusinessConfig;
import com.gzhryc.shared_device.oem.code.place.dao.PlacePhysicalStoreDao;
import com.gzhryc.shared_device.oem.code.place.dao.db.PlacePhysicalStore;
import com.gzhryc.shared_device.oem.code.place.dao.db.PlaceProfitUser;
import com.gzhryc.shared_device.oem.code.place.dao.enums.PlacePhysicalStoreEnum;
import com.gzhryc.shared_device.oem.code.place.event.PlaceGPSEvent;
import com.gzhryc.shared_device.oem.code.place.services.dto.PlacePhysicalStoreSearch;
import com.gzhryc.shared_device.oem.code.user.dao.db.User;

import java.sql.SQLException;
import java.util.*;

public class PlacePhysicalStoreService implements IPlaceService {

    static Logger log = Logger.getLogger(PlacePhysicalStoreService.class);

    public static PlacePhysicalStoreService self() {
        return MultiDBTools.getService(PlacePhysicalStoreService.class, true);
    }

    public static PlacePhysicalStoreService self(String jdbcKey) {
        return MultiDBTools.getService(jdbcKey, PlacePhysicalStoreService.class, true);
    }

    PlacePhysicalStoreDao dao;

    public PlacePhysicalStoreService(String jdbcKey) {
        this.dao = new PlacePhysicalStoreDao(jdbcKey);
    }

    public List<PlacePhysicalStore> findJoinBySearch(PlacePhysicalStoreSearch search, Integer pageNo, Integer pageLimit){
        Conditions conditions = dao.buildConditions(search);
        conditions.and().in("id",search.getPlaceIds());
        conditions.desc("createDate");
        try {
            return dao.findJoinByCondition(conditions,pageNo,pageLimit);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return null;
    }

    public Long countJoinBySearch(PlacePhysicalStoreSearch search){
        Conditions conditions = dao.buildConditions(search);
        conditions.and().in("id",search.getPlaceIds());
        try {
            return dao.countJoin(conditions);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return 0L;
    }

    public List<PlacePhysicalStore> findByIds(List<Long> placeIds){
        if(placeIds != null && placeIds.size() > 0) {
            Conditions conditions = new Conditions(PlacePhysicalStore.class);
            conditions.and().in("id",placeIds);
            try {
                return dao.findByCondition(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }
    
    public List<PlacePhysicalStore> findJoinByIds(List<Long> placeIds){
        if(placeIds != null && placeIds.size() > 0) {
            Conditions conditions = new Conditions(PlacePhysicalStore.class);
            conditions.and().in("id",placeIds);
            try {
                return dao.findJoinByCondition(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

    public List<PlacePhysicalStore> findByUserId(Long userId){
        if(userId != null){
            Conditions conditions = new Conditions(PlacePhysicalStore.class);
            conditions.and().is("userId",userId);

            try {
                return dao.findByCondition(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return null;
    }

    public Long countByAreaCode(String areaCode){
        if(StringTools.isNotBlank(areaCode)){
            Conditions conditions = new Conditions(PlacePhysicalStore.class);
            conditions.and().is("areaCode",areaCode);
            try {
                return dao.count(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return 0L;
    }

    public List<Long> findIdsByUserId(Long userId){
        if(userId != null){
            Conditions conditions = new Conditions(PlacePhysicalStore.class);
            conditions.and().is("userId",userId);

            try {
                return dao.findIdsByConditions(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return null;
    }

    public PlacePhysicalStore getById(Long id){
        try {
            return dao.getById(id);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return null;
    }

    public PlacePhysicalStore getJoinById(Long id){
        try {
            return dao.getJoinById(id);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return null;
    }

    public boolean add(PlacePhysicalStore placePhysicalStore,OperateInfo operateInfo) throws LogicException {
        if(placePhysicalStore != null) {
            if(placePhysicalStore.getUserId() == null){
                throw new LogicException("请填写网点的代理");
            }

            Agent agent = AgentService.self().getByUserId(placePhysicalStore.getUserId());
            if(agent == null){
                throw new LogicException(placePhysicalStore.getUserId() + "非代理用户");
            }

            placePhysicalStore.setState(PlacePhysicalStoreEnum.State.Usable.index());
            placePhysicalStore.setCreateDate(new Date());
            try {
                if (dao.insert(placePhysicalStore) > 0) {
                	//记录日志
                	PlaceLogsRecordService.self().byCreate(placePhysicalStore, operateInfo);
                	
                    if(placePhysicalStore.getLongitude() != null && placePhysicalStore.getLatitude() != null){
                        //触发业务订单创建事件
                        JFKafkaProducer producer = KafkaProducerFactory.self().getProducer();
                        if (producer != null) {
                            PlaceGPSEvent event = new PlaceGPSEvent();
                            event.setPlaceId(placePhysicalStore.getId());
                            event.setType(1);
                            event.setLongitude(placePhysicalStore.getLongitude());
                            event.setLatitude(placePhysicalStore.getLatitude());
                            KafkaMessage kafkaMessage = new KafkaMessage(KafkaEventConstants.TOPIC_Config,
                                    KafkaEventConstants.KEY_PLACE_GPS, JsonTools.toJson(event));
                            producer.send(kafkaMessage);
                        } else {
                            log.error("消息队列未初始化");
                        }
                    }
                    return true;
                }
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return false;
    }
    
    public boolean add(PlacePhysicalStore placePhysicalStore,AgentRelation agentRelation,OperateInfo operateInfo) throws LogicException {
        if(placePhysicalStore != null && agentRelation != null) {
            if(placePhysicalStore.getUserId() == null){
                throw new LogicException("请填写网点的代理");
            }

            Agent agent = AgentService.self().getByUserId(placePhysicalStore.getUserId());
            if(agent == null){
                throw new LogicException(placePhysicalStore.getUserId() + "非代理用户");
            }

            placePhysicalStore.setState(PlacePhysicalStoreEnum.State.Usable.index());
            placePhysicalStore.setCreateDate(new Date());
            
            boolean flag = false;
            
            JdbcSession.begin();
            try {
                if (dao.insert(placePhysicalStore) > 0) {
                	PlaceProfitUser profitUser = new PlaceProfitUser();
                	profitUser.setPlaceId(placePhysicalStore.getId());
                	profitUser.setPlaceUserId(placePhysicalStore.getUserId());
                	profitUser.setRoleType(agentRelation.getRoleType());
                	
                	User user = agentRelation.getRelationUser();
                	if(user == null) {
                		user = new User();
                		user.setId(agentRelation.getRelationUserId());
                	}
                	
                	//记录日志
                	PlaceLogsRecordService.self().byCreate(placePhysicalStore, operateInfo);
                	
                	if(PlaceProfitUserService.self().add(placePhysicalStore,profitUser,user,null,operateInfo)) {
                		JdbcSession.commit();
                		flag = true;
                	}
                }
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            } finally {
            	JdbcSession.end();
            }
            
            if(flag) {
            	if(placePhysicalStore.getLongitude() != null && placePhysicalStore.getLatitude() != null){
                    //触发业务订单创建事件
                    JFKafkaProducer producer = KafkaProducerFactory.self().getProducer();
                    if (producer != null) {
                        PlaceGPSEvent event = new PlaceGPSEvent();
                        event.setPlaceId(placePhysicalStore.getId());
                        event.setType(1);
                        event.setLongitude(placePhysicalStore.getLongitude());
                        event.setLatitude(placePhysicalStore.getLatitude());
                        KafkaMessage kafkaMessage = new KafkaMessage(KafkaEventConstants.TOPIC_Config,
                                KafkaEventConstants.KEY_PLACE_GPS, JsonTools.toJson(event));
                        producer.send(kafkaMessage);
                    } else {
                        log.error("消息队列未初始化");
                    }
                }
                return true;
            }
        }
        return false;
    }

    public boolean updateNotNull(PlacePhysicalStore placePhysicalStore) throws LogicException{
        try {
            if(dao.updateNotNull(placePhysicalStore) > 0){
                if(placePhysicalStore.getLongitude() != null && placePhysicalStore.getLatitude() != null){
                    //触发业务订单创建事件
                    JFKafkaProducer producer = KafkaProducerFactory.self().getProducer();
                    if (producer != null) {
                        PlaceGPSEvent event = new PlaceGPSEvent();
                        event.setPlaceId(placePhysicalStore.getId());
                        event.setType(1);
                        event.setLongitude(placePhysicalStore.getLongitude());
                        event.setLatitude(placePhysicalStore.getLatitude());
                        KafkaMessage kafkaMessage = new KafkaMessage(KafkaEventConstants.TOPIC_Config,
                                KafkaEventConstants.KEY_PLACE_GPS, JsonTools.toJson(event));
                        producer.send(kafkaMessage);
                    } else {
                        log.error("消息队列未初始化");
                    }
                }
                return true;
            }
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return false;
    }

    @Override
    public boolean deployDevice(Long placeId,List<DeviceTypeFunc> deviceTypeFuncList) throws LogicException{
        if(placeId != null && deviceTypeFuncList != null && deviceTypeFuncList.size() > 0) {
            List<String> businessTypes = new ArrayList<>();
            for (DeviceTypeFunc deviceTypeFunc : deviceTypeFuncList) {
                if(StringTools.isNotBlank(deviceTypeFunc.getBusinessType())){
                    if(!businessTypes.contains(deviceTypeFunc.getBusinessType())) {
                        businessTypes.add(deviceTypeFunc.getBusinessType());
                    }
                }
            }

            JdbcSession.begin();
            try {
                boolean flag = true;
                if(businessTypes != null && businessTypes.size() > 0) {
                    for (String businessType : businessTypes) {
                        if (!PlaceBusinessConfigService.self().deploy(placeId, businessType, 1)) {
                            flag = false;
                            break;
                        }
                    }
                }
                if(flag){
                    JdbcSession.commit();
                    return true;
                }
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }  finally {
                JdbcSession.end();
            }
        }
        return false;
    }

    @Override
    public boolean undeployDevice(Long placeId, String deviceSn,String deviceTypeId) throws LogicException {
        if(placeId != null && StringTools.isNotBlank(deviceSn) && StringTools.isNotBlank(deviceTypeId)) {
            //检查是否有工作中订单
            MemberBusinessOrderSearch search = new MemberBusinessOrderSearch();
            search.setDeviceSn(deviceSn);
            search.setState(MemberBusinessOrderEnum.State.Working.index());
            //TODO 当前年的订单
            Long total = MemberBusinessOrderService.self(new Date()).countBySearch(search);
            if(total != null && total > 0){
                throw new LogicException("有工作中订单，不允许移除部署");
            }

            //获取业务的设备数量
            Map<String,Integer> deviceCountMap = new HashMap<>();
            List<PlaceBusinessConfig> businessConfigList = PlaceBusinessConfigService.self().findByPlaceId(placeId);
            if(businessConfigList != null && businessConfigList.size() > 0){
                for(PlaceBusinessConfig businessConfig : businessConfigList) {
                    deviceCountMap.put(businessConfig.getBusinessType(), businessConfig.getDeviceCount());
                }
            }

            List<DeviceTypeFunc> deviceTypeFuncList = DeviceTypeFuncService.self().findByTypeId(deviceTypeId);
            if(deviceTypeFuncList != null && deviceTypeFuncList.size() > 0){
                for(DeviceTypeFunc deviceTypeFunc : deviceTypeFuncList){
                    Integer deviceCount = deviceCountMap.get(deviceTypeFunc.getCode());
                    if(deviceCount != null){
                        deviceCount = deviceCount - 1;
                        if(deviceCount  > 0) {
                            deviceCountMap.put(deviceTypeFunc.getCode(), deviceCount);
                        }else {
                            deviceCountMap.remove(deviceTypeFunc.getCode());
                        }
                    }
                }
            }

            JdbcSession.begin();
            try {
                boolean flag = true;
                if(businessConfigList != null && businessConfigList.size() > 0){
                    for(PlaceBusinessConfig businessConfig : businessConfigList) {
                        boolean toDel = true;
                        Integer deviceCount = deviceCountMap.get(businessConfig.getBusinessType());
                        if(deviceCount != null && deviceCount > 0){
                            toDel = false;
                        }
                        if (toDel) {
                            flag = flag && PlaceBusinessConfigService.self().faceDeleteByKeys(placeId, businessConfig.getBusinessType());
                        } else {
                            flag = flag && PlaceBusinessConfigService.self().undeploy(placeId, businessConfig.getBusinessType(), 1);
                        }
                        if (!flag) {
                            break;
                        }
                    }
                }
                if (flag) {
                    JdbcSession.commit();
                    return true;
                }
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            } catch (LogicException e) {
                log.error(e.getMessage(), e);
            } finally {
                JdbcSession.end();
            }
        }
        return false;
    }

    public boolean deleteById(Long id)throws LogicException{
        if(id != null) {
            PlacePhysicalStore placePhysicalStore = getById(id);
            if(placePhysicalStore == null){
                throw new LogicException("网点不存在");
            }

            Long total = DeviceService.self().countByPlaceId(id);
            if(total != null && total > 0){
                throw new LogicException("网点部署了设备，不允许删除");
            }

            boolean flag = false;
            JdbcSession.begin();
            try {
                if(dao.deleteById(id) > 0){
                    if(PlaceBusinessConfigService.self().deleteByPlaceId(id)){
                        if(PlaceProfitUserService.self().deleteByPlaceId(id)){
                            JdbcSession.commit();
                            flag = true;
                        }
                    }
                }
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }finally {
                JdbcSession.end();
            }

            if(flag){
                if(placePhysicalStore.getLongitude() != null && placePhysicalStore.getLatitude() != null){
                    JFKafkaProducer producer = KafkaProducerFactory.self().getProducer();
                    if (producer != null) {
                        PlaceGPSEvent event = new PlaceGPSEvent();
                        event.setPlaceId(placePhysicalStore.getId());
                        event.setType(2);
                        KafkaMessage kafkaMessage = new KafkaMessage(KafkaEventConstants.TOPIC_Config,
                                KafkaEventConstants.KEY_PLACE_GPS, JsonTools.toJson(event));
                        producer.send(kafkaMessage);
                    } else {
                        log.error("消息队列未初始化");
                    }
                }
                return true;
            }
        }
        return false;
    }

	@Override
	public boolean deployDevice(Long placeId, String businessType,Integer deviceCount) throws LogicException {
		if(placeId != null && StringTools.isNotBlank(businessType)) {
			return PlaceBusinessConfigService.self().deploy(placeId, businessType, deviceCount);
		}
		return false;
	}
}
